package com.lmt.ymcc.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.lmt.ymcc.domain.PayFlow;
import com.lmt.ymcc.domain.PayOrder;
import com.lmt.ymcc.dto.AliPayMessageDto;
import com.lmt.ymcc.dto.AlipayNotifyDto;
import com.lmt.ymcc.exception.GlobalException;
import com.lmt.ymcc.service.IPayFlowService;
import com.lmt.ymcc.service.IPayNotifyService;
import com.lmt.ymcc.service.IPayOrderService;
import com.lmt.ymcc.utils.AssertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: TODO
 * @Author: Amazing
 * @Date: 2022/8/22 9:05
 * @Version: 1.0
 */
@Service
@Slf4j
public class PayNotifyServiceImpl implements IPayNotifyService {

    @Autowired
    private IPayOrderService payOrderService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private IPayFlowService payFlowService;

    @Override
    public String notify(AlipayNotifyDto dto) {
        log.info("接收到支付宝通知");
        // 判断支付宝交易状态
        AssertUtil.isTrue(dto.isTradeSuccess(), "交易失败");
        Map map = JSONObject.parseObject(JSONObject.toJSONString(dto), Map.class);
        try {
            Boolean isVerify = Factory.Payment.Common().verifyNotify(map);
            if (!isVerify) {
                return "SUCCESS";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "ERROR";
        }
        // 判断订单是否正确
        PayOrder payOrder = payOrderService.checkPayOrder(dto.getOut_trade_no());
        if (payOrder == null) {
            return "SUCCESS";
        }
        // 判断金额是否正确
        int amountEq = new BigDecimal(dto.getTotal_amount()).compareTo(payOrder.getAmount());
        if(amountEq != 0){
            return "SUCCESS";
        }
        // 判断支付单状态
        boolean isWaitPay = payOrder.getPayStatus() == PayOrder.STATE_WAIT_PAY;
        if(!isWaitPay){
            try {
                log.info("主动退款....");
                Factory.Payment.Common().refund(payOrder.getOrderNo(),payOrder.getAmount().toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "SUCCESS";
        }
        // 修改支付单状态
        payOrder.setPayStatus(PayOrder.STATE_SUCCESS);
        Date now = new Date();
        payOrder.setUpdateTime(now);
        // 保存支付流水
        PayFlow payFlow = new PayFlow();
        payFlow.setNotifyTime(now);
        payFlow.setSubject(payOrder.getSubject());
        payFlow.setOutTradeNo(dto.getOut_trade_no());
        payFlow.setTotalAmount(new BigDecimal(dto.getTotal_amount()));
        payFlow.setTradeStatus(dto.getTrade_status());
        payFlow.setCode(dto.getCode());
        payFlow.setMsg(dto.getMsg());
        payFlow.setPassbackParams(dto.getPassback_params());
        payFlow.setPaySuccess(dto.isTradeSuccess());
        // 把上面两个信息保存到一个map中，方便后面发事务消息
        HashMap<String, Object> tranMap = new HashMap<>();
        tranMap.put("PayOrder", payOrder);
        tranMap.put("PayFlow", payFlow);
        AliPayMessageDto aliPayMessageDto = new AliPayMessageDto(payOrder.getOrderNo(), payOrder.getExtParams());
        log.info("开启事务消息");
        Message<String> message = MessageBuilder.withPayload(JSON.toJSONString(aliPayMessageDto)).build();
        TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(
                "TxPayAliNotifyGroup",
                "paynofity-topic:alipay-tags",
                message,
                tranMap
        );
        //执行本地事务的状态
        log.info("发送事务消息开始");
        LocalTransactionState localTransactionState = sendResult.getLocalTransactionState();
        //发送消息状态
        SendStatus sendStatus = sendResult.getSendStatus();
        log.info("发送事务消息完成");
        if( localTransactionState != LocalTransactionState.COMMIT_MESSAGE || sendStatus != SendStatus.SEND_OK ){
            throw new GlobalException("处理支付结果失败！请重给我推消息");
        }
        return "SUCCESS";
    }

    @Override
    public void updatePayOrderAndInsertFlow(Map<String, Object> map) {
        PayOrder payOrder = (PayOrder) map.get("PayOrder");
        PayFlow flow = (PayFlow) map.get("PayFlow");
        PayOrder payOrderTmp = payOrderService.selectById(payOrder.getId());
        boolean isWaitePay = payOrderTmp.getPayStatus() == PayOrder.STATE_WAIT_PAY;
        AssertUtil.isTrue(isWaitePay,"信息异常！");
        payOrderService.updateById(payOrder);
        payFlowService.insert(flow);
    }
}
